namespace Plugins.Library
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Threading;

    public abstract class PluginSequentialWorkItemContainer<T> : PluginWorkItemContainer<T>, IDisposable
    {
        private static object _sync = new object();

        private AutoResetEvent _handle;

        protected PluginSequentialWorkItemContainer(T item) : base(item)
        {
            this._handle = new AutoResetEvent(false);
        }

        protected override void EndProcess()
        {
            PluginSequentialWorkItemContainer<T>.Signal((PluginSequentialWorkItemContainer<T>) this);
        }

        protected override void BeginProcess()
        {
            PluginSequentialWorkItemContainer<T>.Wait((PluginSequentialWorkItemContainer<T>) this);
        }

        [SuppressMessage("Microsoft.Design", "CA1000")]
        public static void QueryAsync(PluginSequentialWorkItemContainer<T> item)
        {
            lock (_sync)
            {
                if (item != null)
                {
                    item.Link = PluginWorkItemContainer<T>.Current;
                    PluginWorkItemContainer<T>.Current = item;
                    PluginWorkItemContainer<T>.QueryAsync(item);
                }
            }
        }

        [SuppressMessage("Microsoft.Design", "CA1000")]
        public static void QuerySync(PluginSequentialWorkItemContainer<T> item)
        {
            lock (_sync)
            {
                if (item != null)
                {
                    item.Link = PluginWorkItemContainer<T>.Current;
                    PluginWorkItemContainer<T>.Current = item;
                    PluginWorkItemContainer<T>.QuerySync(item);
                }
            }
        }

        [SuppressMessage("Microsoft.Design", "CA1000")]
        public static void Signal(PluginWorkItemContainer<T> item)
        {
            if (item != null)
            {
                item.Signal();
            }
        }

        public override void Signal()
        {
            _handle.Set();
        }

        public override void Wait()
        {
            _handle.WaitOne();
        }

        [SuppressMessage("Microsoft.Design", "CA1000")]
        public static void Wait(PluginWorkItemContainer<T> item)
        {
            if (item != null)
            {
                PluginWorkItemContainer<T> previous = item.Link;
                if (previous != null)
                {
                    previous.Wait();
                }
            }
        }

        [SuppressMessage("Microsoft.Design", "CA1000")]
        public static void Sync(PluginWorkItemContainer<T> item)
        {
            if (item != null)
            {
                item.Wait();
            }
        }

        #region IDisposable Members

        [SuppressMessage("Microsoft.Design", "CA1063")]
        [SuppressMessage("Microsoft.Usage", "CA1816")]
        public void Dispose()
        {
            ((IDisposable)_handle).Dispose();
            GC.SuppressFinalize(this);
        }

        #endregion
    }
}

